<template>
    <div>
        <button type="button" @click="selectFile" class="btn btn-white btn-default btn-round">
            <i class="ace-icon fa fa-upload"></i>
            {{text}}
        </button>
        <br/>
        <input class="hidden" type="file" ref="file" v-bind:id="inputId+'-input'" v-on:change="uploadFile">
    </div>
</template>

<script>
  import axios from "axios";

  export default {
    name: 'oss-big-file',
    props: {
      text: {
        default: "上传大文件"
      },
        afterUpload:{
            type: Function,
            default: null
        },
        inputId:{
          default: "file-upload"
        },
        shardSize:{
            default: 10 * 1024 * 1024
        },
        url:{
            default: "oss-append"
        },
        suffixs:{
            default: []
        },
        use:{
          default:""
        }
    },
    data: function () {
      return {
          flag: false
      }
    },
    methods: {
        /*
              * 头像上传
              * */
         uploadFile(){
             let _this=this;
            //定义一个表单
            // let formData=new window.FormData();
            //拿到file组件
            let file_info=this.$refs.file.files[0];
            //判断文件格式
            let suffixs=this.suffixs;
            let use=_this.use;
            let fileName=file_info.name;
            let suffix=fileName.substring(fileName.lastIndexOf(".")+1,fileName.length).toLowerCase();
            let validateSuffix=false;
            for(let i=0;i<suffixs.length;i++){
                if(suffixs[i].toLowerCase()===suffix){
                    validateSuffix=true;
                    break;
                }
            }

            if(!validateSuffix){
                Toast.warning("文件格式不正确!,只支持:"+suffixs.join(","));
                $('#'+this.inputId+"-input").val("");
                return;
            }
            //获取文件标识
            let key =hex_md5(file_info.name+file_info.type+file_info.size);

            //文件分片
             let shardSize= _this.shardSize; //以10MB为一个分片
             let shardIndex=1;//分片索引,1为第一个分片.

             let size=file_info.size;
             // console.log("文件大小",size);
             let shardTotal=Math.ceil(size / shardSize);//总分片数

             let param={
                 "use": use,
                 "shardIndex": shardIndex,
                 "shardSize": shardSize,
                 "shardTotal":shardTotal,
                 "size": size,
                 "key": key,
                 "name":fileName,
                 "suffix": suffix
             };

             this.check(param);

         },
        //获取fileShard
        getFileShard: function (shardIndex, shardSize) {
             let _this=this;
            let file_info=_this.$refs.file.files[0];
            let start = (shardIndex - 1) * shardSize;//计算当前分片起始位置
            // let end=start + shardSize;//当前分片结束位置,此算法有误，若文件为25MB则end会等于30mb
            let end = Math.min(file_info.size, start + shardSize);//当前分片结束位置
            let fileShard = file_info.slice(start, end);//从文件中截取当前的分片数据
            return fileShard;
        },
        //上传分片
        upload: function (param) {
            let _this=this;
             let shardIndex=param.shardIndex;
             let shardTotal=param.shardTotal;
             let shardSize=param.shardSize;
            let fileShard = _this.getFileShard(shardIndex, shardSize);
            //将文件转为base64进行传输
            let fileReader = new FileReader();
            //弹出进度条
            Progress.show(parseInt((shardIndex-1)*100)/shardTotal);

            fileReader.onload = function (e) {
                let base64 = e.target.result;
                //对param的shard赋值
                param.shard = base64;
                axios.post("/file/admin/"+_this.url, param).then((response) => {
                    const data = response.data;
                    if (data.success) {
                        //弹出进度条
                        Progress.show(parseInt(shardIndex*100)/shardTotal);
                        if (shardIndex < shardTotal) {
                            //上传下一个分片
                            param.shardIndex +=1;
                            //递归
                            _this.upload(param);
                        } else {
                            Progress.hide();
                            //清空控件中的值
                            $('#' + this.inputId + "-input").val("");
                            //调用外部函数
                            _this.afterUpload(data);
                        }

                        let fileInfo = data.content;
                        console.log("上传文件信息: ", fileInfo);

                    }
                });
            };
            fileReader.readAsDataURL(fileShard);
        },
        //合并分片
         mergeShard(param){
             return  axios.post("/file/admin/merge", param);
          },

        /*
        * 触发上传按钮
        * */
        selectFile(){
            $('#'+this.inputId+"-input").trigger("click");
        },
        check(param){
            let _this=this;
            axios.get("/file/admin/check/"+param.key).then((response)=>{
                const data=response.data;
                if(data.success){
                    const obj=data.content;
                    if(!obj){
                        //没有文件记录
                        console.log("没有文件记录")
                        param.shardIndex =1;
                        _this.upload(param);
                    }else if (obj.shardIndex=== obj.shardTotal){
                            //分片索引===分片总数，说明文件已经上传完
                            Toast.success("文件极速秒传成功!");
                             //调用暴露给组件外部的函数
                            _this.afterUpload(data);
                            //清空控件中的值
                            $('#' + this.inputId + "-input").val("");
                    } else{
                        //找到文件记录，从分片索引+1开始传
                        param.shardIndex=obj.shardIndex +1;
                        console.log("找到记录,开始上传",param.shardIndex);
                        _this.upload(param);
                    }
                }else {
                    Toast.error("文件检查失败!");
                    $('#' + this.inputId + "-input").val("");
                }
            })
        }
    }
  }
</script>